import tkinter as tk
from tkinter import scrolledtext, PanedWindow, filedialog
import csv
import re
from collections import defaultdict


def process_bta_data(bta_data):
    array_counts = defaultdict(int)
    unique_bta_data = []

    # 使用字典来存储已经处理过的数组内容
    seen_arrays = defaultdict(set)

    for item in bta_data:
        array_name_start = item.find("BTA_")  # 找到数组名的起始位置
        if array_name_start != -1:
            array_name_end = item.find(" ", array_name_start)  # 找到数组名的结束位置
            if array_name_end != -1:
                array_name = item[array_name_start:array_name_end]  # 提取数组名部分
                array_content = item[array_name_end + 1:].strip()  # 提取数组内容部分

                if array_content in seen_arrays[array_name]:
                    # 如果数组名和内容已经存在于 seen_arrays 中，则不添加到 unique_bta_data 中
                    continue

                seen_arrays[array_name].add(array_content)

                if array_name in array_counts:
                    array_counts[array_name] += 1
                    new_array_name = f"{array_name}_{array_counts[array_name]}"
                    unique_bta_data.append(item.replace(array_name, new_array_name, 1))
                else:
                    array_counts[array_name] = 0
                    unique_bta_data.append(item)
            else:
                unique_bta_data.append(item)
        else:
            unique_bta_data.append(item)

    return unique_bta_data


def read_csv_and_process_bta(output_textbox, file_path):
    bta_data = []
    debug_info = []  # 用于存储调试信息
    dt_index = None
    d0_index = None
    wc_index = None  # 添加了 WC 的索引
    lp_bta_count = 0  # 记录 LP_BTA 的计数
    processing_lp_bta = False  # 标记是否正在处理 LP_BTA 的下一行数据

    try:
        with open(file_path, 'r', encoding='utf-8-sig') as csvfile:
            csvreader = csv.reader(csvfile)
            header = next(csvreader)  # 读取标题行

            # 确定 DT、D0 和 WC 的索引
            if header:
                dt_index = header.index("DT")
                d0_index = header.index("D0")
                wc_index = header.index("WC")

            previous_row = None
            for row_num, row in enumerate(csvreader, start=2):  # 行号从第二行开始计数
                debug_info.append(f"处理第 {row_num} 行数据...")

                mode = row[1].strip().strip('="')  # 去除额外的等号和引号
                dt_value = row[dt_index].strip().strip('="') if dt_index is not None else ''
                d0_value = row[d0_index].strip().strip('="') if d0_index is not None else ''
                data_values = [val.strip() for val in row[6:14] if val.strip() and val.strip().startswith("0x")]

                debug_info.append(f"Mode: {mode}, DT: {dt_value}, D0: {d0_value}")

                if processing_lp_bta:
                    # 处理 LP_BTA 的下一行数据
                    if mode == 'LP_ESC':
                        # 提取 dcs dt
                        dcs_value = row[dt_index].strip().strip('="')[-3:-1] if len(row) > 6 else ''
                        if dcs_value:
                            # 提取 DCS Long READ Response (1C) 的 -3 到 -1 的字符
                            wc_value_str = row[wc_index].strip().strip('="')
                            # print(f"wc_value_str:{wc_value_str}")
                            # if wc_index is not None else ''
                            # if wc_value_str:
                            if wc_value_str == ' ':
                                wc_value = '0002'
                                # print("wc_value_str = ''")
                            else:
                                wc_value = wc_value_str[-4:]  # 获取后四位字符，确保长度为4

                            # 检查十六进制字符串是否有效
                            if all(c in '0123456789abcdefABCDEF' for c in wc_value) and len(wc_value) == 4:
                                wc_value_int = int(wc_value, 16)  # 将十六进制转换为整数
                                # print(f"WC value: {wc_value} ({wc_value_int})")

                                # 获取后续数据
                                additional_data = [f"0x{dcs_value}"]  # 将 DCS 值加入 additional_data
                                additional_data.extend([wc_value])
                                additional_data.extend([val.strip().strip('="') for val in row[7:7 + wc_value_int] if val.strip() and val.strip()])# .startswith("0x")
                                # print(f"{additional_data}")
                                # 构建数组名称和数据
                                array_name = f"uint32_t BTA_{previous_dt_value}_{previous_d0_value}"

                                if wc_value_int > 2:
                                    long_package_data = []
                                    wc1 = wc_value[0:2] if len(wc_value) > 1 else '00'
                                    wc0 = wc_value[2:4] if len(wc_value) > 3 else '00'
                                    # 第一行数据格式
                                    first_line_data = f"00{wc1}{wc0}{dcs_value}"
                                    long_package_data.append(first_line_data)

                                    # 按照顺序提取 D3 D2 D1 D0
                                    for i in range(2, len(additional_data), 4):
                                        chunk = additional_data[i:i + 4]
                                        if len(chunk) < 4:
                                            chunk = ['00'] * (4 - len(chunk)) + chunk  # 补充 '00'
                                        chunk = ['0x'] + chunk  # 补充 '00'
                                        long_package_data.append(''.join(chunk))

                                    # 构建数组名称和数据
                                    # array_name = f"uint32_t BTA_{dt_value}_{d0_value}"
                                    array_content = ',\n'.join(long_package_data)
                                    bta_data.append(f"{array_name} = {{\n0x{array_content}\n}}")
                                    debug_info.append(f"提取的数组名称: {array_name}")
                                    # array_content = ', '.join(long_package_data)

                                else:
                                    # 短包数据填充方法
                                    short_package_data = ['\n''0x00', '00']
                                    if len(additional_data) > 2:
                                        short_package_data.append(additional_data[2])
                                    else:
                                        short_package_data.append('00')
                                    short_package_data.append(dcs_value+'\n')

                                    # 连接数据为一个字符串，没有分隔符
                                    array_content = ''.join(short_package_data)

                                    bta_data.append(f"{array_name} = {{{array_content}}}")
                                    debug_info.append(f"提取的数组名称: {array_name}")

                            else:
                                debug_info.append(f"错误：无效的十六进制字符 '{wc_value}' 或长度不为4")

                        # 处理完 LP_BTA 的下一行数据
                        processing_lp_bta = False

                if mode == 'LP_BTA':
                    lp_bta_count += 1
                    debug_info.append(f"LP_BTA 计数: {lp_bta_count}")

                    if lp_bta_count % 2 != 0:
                        # 第一次或奇数次出现 LP_BTA，需要提取数据
                        if previous_row:
                            previous_dt_value = previous_row[dt_index].strip().strip('="')[-3:-1] if dt_index is not None else ''
                            previous_d0_value = previous_row[d0_index].strip().strip('="') if d0_index is not None else ''
                            debug_info.append(f"Previous DT value: {previous_dt_value}")
                            debug_info.append(f"Previous D0 value: {previous_d0_value}")

                            if previous_dt_value and previous_d0_value:
                                processing_lp_bta = True  # 标记需要处理下一行数据
                            else:
                                debug_info.append("未找到 DT 或 D0 中的数字部分")

                # 打印当前行信息
                debug_info.append(f"当前行数据 - Mode: {mode}, DT: {dt_value}, D0: {d0_value}, 数据: {', '.join(data_values)}")

                # 更新上一行数据
                previous_row = row

        # 筛除重复数组 并对数组名相同但数组内容不相同的BTA进行重命名
        bta_data = process_bta_data(bta_data)
        # 在文本框中显示处理结果和调试信息
        output_textbox.delete('1.0', tk.END)  # 清空文本框
        if bta_data:
            output_textbox.insert(tk.END, "提取的 BTA 数据:\n")
            for item in bta_data:
                output_textbox.insert(tk.END, item + "\n")
        else:
            output_textbox.insert(tk.END, "未找到符合条件的 BTA 数据。\n")

        # 显示调试信息
        # output_textbox.insert(tk.END, "\n调试信息:\n")
        # for info in debug_info:
        #     output_textbox.insert(tk.END, info + "\n")

    except FileNotFoundError:
        output_textbox.delete('1.0', tk.END)  # 清空文本框
        output_textbox.insert(tk.END, f"错误：找不到文件 {file_path}\n")
    except Exception as e:
        output_textbox.delete('1.0', tk.END)  # 清空文本框
        output_textbox.insert(tk.END, f"错误：{str(e)}\n")


# 处理按钮点击事件：选择并处理 CSV 文件
def handle_read_csv(output_textbox, file_path):
    output_textbox.delete('1.0', tk.END)  # 清空文本框

    try:
        with open(file_path, 'r', newline='', encoding='utf-8-sig') as csvfile:
            reader = csv.reader(csvfile)
            for row in reader:
                output_textbox.insert(tk.END, ', '.join(row) + '\n')

        if output_textbox.get('1.0', tk.END).strip() == '':
            output_textbox.insert(tk.END, "未找到数据或文件为空。\n")

    except FileNotFoundError:
        output_textbox.insert(tk.END, f"错误：找不到文件 {file_path}\n")
    except Exception as e:
        output_textbox.insert(tk.END, f"错误：{str(e)}\n")


def open_csv_file_and_process(output_textbox):
    file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
    if file_path:  # 确保用户选择了文件
        read_csv_and_process_bta(output_textbox, file_path)


# 函数：提取特定命令数据
def extract_specific_command_data(text, command_name, header_value=None):
    lines = text.splitlines()
    extracted_data = []
    index = 0

    for line in lines:
        if line.strip().startswith(command_name):
            start_idx = line.find("(") + 1
            end_idx = line.find(");", start_idx)
            if end_idx == -1:
                continue

            params_str = line[start_idx:end_idx].strip()
            params = params_str.split(',')
            hex_data = [p.strip() for p in params if p.strip().startswith("0x")]

            if hex_data:
                if header_value is None:
                    header_value = 0x29  # 默认指令头为0x29

                array_name = f"cmd{index}"
                data_length = len(hex_data)
                array_content = [f"0x{header_value:02X}", f"0x{data_length:02X}"] + ["0x00"] + hex_data
                array_definition = f"static uint8_t {array_name}[] = {{{', '.join(array_content)}}};"
                extracted_data.append(array_definition)
                index += 1

    return extracted_data


# 提取数据界面
def extract_gui():
    def extract_data():
        input_text = input_textbox.get("1.0", tk.END)
        command_name = command_entry.get().strip()
        header_value_str = header_entry.get().strip()

        if header_value_str.startswith("0x"):
            header_value = int(header_value_str, 16)
        else:
            header_value = None

        extracted_data = extract_specific_command_data(input_text, command_name, header_value)

        output_textbox.delete("1.0", tk.END)
        for data in extracted_data:
            output_textbox.insert(tk.END, data + "\n")

    extract_window = tk.Toplevel()
    extract_window.title("提取指定命令数据")

    paned_window = PanedWindow(extract_window, orient=tk.HORIZONTAL, sashrelief=tk.RAISED, sashwidth=5)
    paned_window.pack(fill=tk.BOTH, expand=True)

    left_frame = tk.Frame(extract_window)
    right_frame = tk.Frame(extract_window)

    paned_window.add(left_frame)
    paned_window.add(right_frame)

    input_label = tk.Label(left_frame, text="请粘贴要处理的命令文本:")
    input_label.pack(fill=tk.X, padx=5, pady=5)

    input_textbox = scrolledtext.ScrolledText(left_frame, width=40, height=15)
    input_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

    command_label = tk.Label(left_frame, text="请输入要提取的命令名称（例如：GEN_WR）: 留空则默认为GEN_WR")
    command_label.pack(fill=tk.X, padx=5, pady=5)

    command_entry = tk.Entry(left_frame)
    command_entry.pack(fill=tk.X, padx=5, pady=5)

    header_label = tk.Label(left_frame, text="请输入指令头的十六进制数值（例如：0x29），留空则默认为0x29:")
    header_label.pack(fill=tk.X, padx=5, pady=5)

    header_entry = tk.Entry(left_frame)
    header_entry.pack(fill=tk.X, padx=5, pady=5)

    extract_button = tk.Button(left_frame, text="提取数据", command=extract_data)
    extract_button.pack(pady=10)

    output_label = tk.Label(right_frame, text="提取结果:")
    output_label.pack(fill=tk.X, padx=5, pady=5)

    global output_textbox
    output_textbox = scrolledtext.ScrolledText(right_frame, width=40, height=15)
    output_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)


# 转换数据界面
def convert_gui():
    def convert_data():
        hex_data = hex_textbox.get("1.0", tk.END)
        converted_data = convert_hex_to_array(hex_data)

        converted_textbox.delete("1.0", tk.END)
        for data in converted_data:
            converted_textbox.insert(tk.END, data + "\n")

    convert_window = tk.Toplevel()
    convert_window.title("PPS 十六进制数据转换为数组")

    paned_window = PanedWindow(convert_window, orient=tk.HORIZONTAL, sashrelief=tk.RAISED, sashwidth=5)
    paned_window.pack(fill=tk.BOTH, expand=True)

    left_frame = tk.Frame(convert_window)
    right_frame = tk.Frame(convert_window)

    paned_window.add(left_frame)
    paned_window.add(right_frame)

    hex_label = tk.Label(left_frame, text="请粘贴要转换的PPS 十六进制数据（每行以空格分隔）:")
    hex_label.pack(fill=tk.X, padx=5, pady=5)

    hex_textbox = scrolledtext.ScrolledText(left_frame, width=40, height=15)
    hex_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

    convert_button = tk.Button(left_frame, text="转换数据", command=convert_data)
    convert_button.pack(pady=10)

    converted_label = tk.Label(right_frame, text="转换后的数据:")
    converted_label.pack(fill=tk.X, padx=5, pady=5)

    converted_textbox = scrolledtext.ScrolledText(right_frame, width=40, height=15)
    converted_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)


def create_main_gui():
    global output_textbox

    root = tk.Tk()
    root.title("数据处理工具")

    extract_button = tk.Button(root, text="提取指定命令数据", command=extract_gui)
    extract_button.pack(pady=20)

    convert_button = tk.Button(root, text="PPS/十六进制数据转换为数组", command=convert_gui)
    convert_button.pack(pady=20)

    excel_button = tk.Button(root, text="从 CSV 读取数据 提取BTA", command=lambda: open_csv_file_and_process(output_textbox))
    excel_button.pack(pady=20)

    # 创建 output_textbox
    output_textbox = scrolledtext.ScrolledText(root, width=40, height=15)
    output_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
    root.mainloop()


# 启动主界面
if __name__ == "__main__":
    create_main_gui()